package cn.itsource.service.impl;

import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.itsource.constants.CacheConstants;
import cn.itsource.constants.ErrorCode;
import cn.itsource.constants.RConst;
import cn.itsource.domain.Login;
import cn.itsource.mapper.LoginMapper;
import cn.itsource.pojo.dto.RegisterDto;
import cn.itsource.pojo.ro.AdminLoginRo;
import cn.itsource.pojo.ro.AppLoginRo;
import cn.itsource.pojo.ro.ResetPasswordRo;
import cn.itsource.pojo.vo.AdminLoginVo;
import cn.itsource.pojo.vo.AppLoginVo;
import cn.itsource.result.JSONResult;
import cn.itsource.service.ILoginService;
import cn.itsource.service.WxService;
import cn.itsource.utils.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 登录表 服务实现类
 * </p>
 *
 * @author zls
 * @since 2024-07-06
 */
@Service
@Slf4j
@Transactional
public class LoginServiceImpl extends ServiceImpl<LoginMapper, Login> implements ILoginService {
    @Autowired
    private WxService wxService;
    @Autowired
    private LoginMapper loginMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public JSONResult appLogin(AppLoginRo loginRo) {
        //获取openId
        RegisterDto registerDto = wxService.getOpenId(loginRo.getCode());
        //获取openId
        String openid = registerDto.getOpenid();
        AssertUtil.isNotNull(registerDto.getOpenid(),"获取openId失败");
        Login one = super.getOne(new LambdaQueryWrapper<Login>().eq(Login::getOpenId, openid).eq(Login::getType, loginRo.getType()));
        if (one!=null){
            getPermissionList(one);
            String tokenValue = StpUtil.getTokenValue();
            AppLoginVo appLoginInfo = AppLoginVo.toAppLoginInfo(one,tokenValue);
            return JSONResult.success(appLoginInfo);
        }
        return JSONResult.error(ErrorCode.SERVICE_APP_LOGIN_ERROR);
    }

    @Override
    public JSONResult test() {
        return JSONResult.success("sdjkd");
    }

    @Override
    public JSONResult adminLogin( AdminLoginRo loginRo) {
        //根据前端的用户名 密码 类型 判断登录
        String username = loginRo.getUsername();
        Integer type = loginRo.getType();
        Login one = super.getOne(new LambdaQueryWrapper<Login>().eq(Login::getUsername, username).eq(Login::getType, type));
        //判断当前用户是否存在
        AssertUtil.isNotNull(one,"用户名或密码错误");
        String password = loginRo.getPassword();
        //判断 当前用户密码是否正确

        boolean matches = passwordEncoder.matches(loginRo.getPassword(), one.getPassword());
        AssertUtil.isTrue(matches,"用户名或密码错误");
        //判断 当前用户是否禁用
        AssertUtil.isTrue(one.getEnabled(),"当前用户被禁用");
        //获取当前权限
        List<String> permissionList = getPermissionList(one);
        String tokenValue = StpUtil.getTokenValue();
        AdminLoginVo adminLoginVo = new AdminLoginVo(tokenValue,permissionList,one);
        return JSONResult.success(adminLoginVo);
    }

    @Override
    public JSONResult logout() {
        String loginId = (String)StpUtil.getLoginId();
        StpUtil.logout(loginId);
        redisTemplate.delete(loginId);
        String key =CacheConstants.CURRENT_LOGIN_PERMISSION+loginId;
        redisTemplate.delete(key);
        return JSONResult.success("退出成功");
    }

    @Override
    public JSONResult resetPassword(ResetPasswordRo passwordRo) {
        Long loginId = Long.valueOf((String)StpUtil.getLoginId());
        String newPassword = passwordRo.getNewPassword();
        String password = passwordRo.getOldPassword();
        AssertUtil.isNotEquals(password,newPassword,"新密码跟旧密码一致");
        String encode = passwordEncoder.encode(newPassword);
        Login one = super.getOne(new LambdaQueryWrapper<Login>().eq(Login::getId,loginId));
        boolean matches = passwordEncoder.matches(password, one.getPassword());
        AssertUtil.isTrue(matches,"用户名或密码错误");
        if (matches){
            super.update(new LambdaUpdateWrapper<Login>().eq(Login::getId,loginId)
                    .set(Login::getPassword,encode));
            return JSONResult.success();
        }
        return JSONResult.error(ErrorCode.SERVICE_NOT_UPDATE_PASSWORD);
    }


    private List<String> getPermissionList(Login one){
        //将头像，电话，性别等信息存进去 交到前端
        StpUtil.login(one.getId(),SaLoginConfig.setExtra("userInfo",one).setExtra("openId",one.getOpenId()));
        //设置key
        //将权限存入redis
        List<String> permissionList = loginMapper.getPermissionList(one.getId());
        String key = CacheConstants.CURRENT_LOGIN_PERMISSION+ one.getId().toString();
        redisTemplate.opsForValue().set(key,permissionList, RConst.Num.INT_30, TimeUnit.MINUTES);
        return permissionList;
    }
}
